package util

import (
	"crypto/hmac"
	"crypto/md5"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"unicode"
)

// 其他类型转换为字符串
func ToString(value any) (string, error) {
	// 使用反射来判断值的类型，并相应地转换为字符串
	v := reflect.ValueOf(value)
	if !v.IsValid() {
		return "", nil
	}
	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return strconv.FormatInt(v.Int(), 10), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return strconv.FormatUint(v.Uint(), 10), nil
	case reflect.Float32, reflect.Float64:
		return strconv.FormatFloat(v.Float(), 'f', -1, 64), nil
	case reflect.Bool:
		return strconv.FormatBool(v.Bool()), nil
	case reflect.String:
		return v.String(), nil
	// 根据需要添加更多的类型处理
	default:
		return "", fmt.Errorf("string类型转换，不支持类型： %s", v.Type())
	}
}

// 字符串转换为int64
func StringToInt64(str string) (int64, error) {
	if str == "" {
		return 0, nil
	}
	num, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		return 0, err
	}
	return num, nil
}

// 大写格式转换为下划线分割（兼容首字母大小写情况）
func UppercaseToUnderline(str string) string {
	re := regexp.MustCompile(`([a-z])([A-Z])`)
	result := re.ReplaceAllStringFunc(str, func(s string) string {
		return s[:1] + "_" + strings.ToLower(s[1:])
	})
	return result
}

// 密码生成
// 根据传入密码和盐值生成密码md5值
func PasswordGenerate(password string, salt string) string {
	hash := hmac.New(md5.New, []byte(salt))
	hash.Write([]byte(password))
	hashed := hex.EncodeToString(hash.Sum(nil))
	return hashed
}

// 字符串首字母大写
func UcFirst(str string) string {
	if len(str) == 0 {
		return str
	}
	runes := []rune(str)
	runes[0] = unicode.ToUpper(runes[0])
	return string(runes)
}

// 字符串首字母小写
func LcFirst(str string) string {
	if len(str) == 0 {
		return str
	}
	runes := []rune(str)
	runes[0] = unicode.ToLower(runes[0])
	return string(runes)
}

// Base64Encode 实现类似 PHP 的 base64_encode 功能
func Base64Encode(str string) string {
	// 将字符串转换为字节切片
	byteData := []byte(str)
	// 使用标准 Base64 编码对字节切片进行编码
	encoded := base64.StdEncoding.EncodeToString(byteData)
	return encoded
}

// 图标class
func IconClass(class string) string {
	if class == "" {
		return class
	}
	if strings.Contains(class, "layui-icon-") && !strings.Contains(class, "layui-icon ") {
		class = "layui-icon " + class
	} else if strings.Contains(class, "yunj-icon-") && !strings.Contains(class, "yunj-icon ") {
		class = "yunj-icon " + class
	}
	return class
}

// 缩短JSON内的字符串，截断其中的长字符串
func TruncateJson(jsonStr string, maxLen int) (string, error) {
	var data any

	// 解析JSON
	if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
		return "", fmt.Errorf("缩短JSON字符串，JSON解析失败: %w", err)
	}

	// 处理解析后的数据
	truncatedData := TruncateValue(data, maxLen)

	// 重新编码为JSON
	result, err := json.Marshal(truncatedData)
	if err != nil {
		return "", fmt.Errorf("缩短JSON字符串，JSON编码失败: %w", err)
	}

	return string(result), nil
}

// 缩短各种类型值中的长字符串
func TruncateValue(value any, maxLen int) any {
	if value == nil {
		return nil
	}

	switch val := value.(type) {
	case string:
		if len(val) <= maxLen {
			return val
		}
		return val[:maxLen] + "..."
	case map[string]any:
		result := make(map[string]any, len(val))
		for k, v := range val {
			result[k] = TruncateValue(v, maxLen)
		}
		return result
	case []any:
		result := make([]any, len(val))
		for i, v := range val {
			result[i] = TruncateValue(v, maxLen)
		}
		return result
	default:
		// 其他类型（数字、布尔等）直接返回
		return val
	}
}
